#region

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using Autofac;
using Autofac.Builder;
using Autofac.Core;
using Autofac.Integration.Mvc;
using HouseHoldBudget.Core;
using HouseHoldBudget.Core.Configuration;
using HouseHoldBudget.Core.Data;
using HouseHoldBudget.Core.Infrastructure;
using HouseHoldBudget.Core.Infrastructure.DependencyManagement;
using HouseHoldBudget.Data;
using HouseHoldBudget.Services.Budgets;
using HouseHoldBudget.Services.Expenses;
using HouseHoldBudget.Services.Incomes;
using HouseHoldBudget.Services.Users;

#endregion

namespace HouseHoldBudget.Framework
{
    public class DependencyRegistrar : IDependencyRegistrar
    {
        #region IDependencyRegistrar Members

        /// <summary>
        /// Registers the specified builder.
        /// </summary>
        /// <param name="builder">The builder.</param>
        /// <param name="typeFinder">The type finder.</param>
        public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder)
        {
            //HTTP context and other related stuff
            builder.Register(c =>
                (new HttpContextWrapper(HttpContext.Current) as HttpContextBase)).As<HttpContextBase>()
                .InstancePerHttpRequest();
            builder.Register(c => c.Resolve<HttpContextBase>().Request)
                .As<HttpRequestBase>()
                .InstancePerHttpRequest();
            builder.Register(c => c.Resolve<HttpContextBase>().Response)
                .As<HttpResponseBase>()
                .InstancePerHttpRequest();
            builder.Register(c => c.Resolve<HttpContextBase>().Server)
                .As<HttpServerUtilityBase>()
                .InstancePerHttpRequest();
            builder.Register(c => c.Resolve<HttpContextBase>().Session)
                .As<HttpSessionStateBase>()
                .InstancePerHttpRequest();

            //controllers
            builder.RegisterControllers(typeFinder.GetAssemblies().ToArray());

            //data layer
            var dataSettingsManager = new DataSettingsManager();
            var dataProviderSettings = dataSettingsManager.LoadSettings();
            builder.Register(c => dataSettingsManager.LoadSettings()).As<DataSettings>();
            builder.Register(x => new EfDataProviderManager(x.Resolve<DataSettings>())).As<BaseDataProviderManager>().InstancePerDependency();
            builder.Register(x => (IEfDataProvider) x.Resolve<BaseDataProviderManager>().LoadDataProvider()).As<IDataProvider>().InstancePerDependency();
            builder.Register(x => (IEfDataProvider) x.Resolve<BaseDataProviderManager>().LoadDataProvider()).As<IEfDataProvider>().InstancePerDependency();
            if (dataProviderSettings != null && dataProviderSettings.IsValid())
            {
                var efDataProviderManager = new EfDataProviderManager(dataSettingsManager.LoadSettings());
                var dataProvider = (IEfDataProvider) efDataProviderManager.LoadDataProvider();
                dataProvider.InitConnectionFactory();

                builder.Register<IDbContext>(c => new ObjectContext(dataProviderSettings.DataConnectionString)).InstancePerHttpRequest();
            }
            else
            {
                builder.Register<IDbContext>(c => new ObjectContext(dataSettingsManager.LoadSettings().DataConnectionString)).InstancePerHttpRequest();
            }
            builder.RegisterGeneric(typeof (EfRepository<>)).As(typeof (IRepository<>)).InstancePerHttpRequest();

            //work context
            builder.RegisterType<WorkerContext>().As<IWorkerContext>().InstancePerHttpRequest();

            //services
            builder.RegisterType<UserService>().As<IUserService>().InstancePerHttpRequest();
            builder.RegisterType<ExpenseService>().As<IExpenseService>().InstancePerHttpRequest();
            builder.RegisterType<ExpenseTypesService>().As<IExpenseTypesService>().InstancePerHttpRequest();
            builder.RegisterType<BudgetService>().As<IBudgetService>().InstancePerHttpRequest();
            builder.RegisterType<BudgetCategoryService>().As<IBudgetCategoryService>().InstancePerHttpRequest();
            builder.RegisterType<FixedIncomesService>().As<IFixedIncomesService>().InstancePerHttpRequest();
        }

        /// <summary>
        /// Gets the order in the registration process
        /// </summary>
        /// <value>
        /// The order.
        /// </value>
        public int Order
        {
            get
            {
                return 0;
            }
        }

        #endregion
    }


    //public class SettingsSource : IRegistrationSource
    //{
    //    #region Readonly & Static Fields

    //    private static readonly MethodInfo BuildMethod = typeof (SettingsSource).GetMethod(
    //        "BuildRegistration",
    //        BindingFlags.Static | BindingFlags.NonPublic);

    //    #endregion

    //    #region IRegistrationSource Members

    //    public IEnumerable<IComponentRegistration> RegistrationsFor(
    //        Service service,
    //        Func<Service, IEnumerable<IComponentRegistration>> registrations)
    //    {
    //        var ts = service as TypedService;
    //        if (ts != null && typeof (ISettings).IsAssignableFrom(ts.ServiceType))
    //        {
    //            var buildMethod = BuildMethod.MakeGenericMethod(ts.ServiceType);
    //            yield return (IComponentRegistration) buildMethod.Invoke(null, null);
    //        }
    //    }

    //    public bool IsAdapterForIndividualComponents
    //    {
    //        get
    //        {
    //            return false;
    //        }
    //    }

    //    #endregion

    //    #region Class Methods

    //    private static IComponentRegistration BuildRegistration<TSettings>() where TSettings : ISettings, new()
    //    {
    //        return RegistrationBuilder
    //            .ForDelegate((c, p) => c.Resolve<IConfigurationProvider<TSettings>>().Settings)
    //            .InstancePerHttpRequest()
    //            .CreateRegistration();
    //    }

    //    #endregion
    //}
}